#include "gui/layers/InfoLayer.h"
#include "gui/objects/GUIHud.h"
#include "util/events/CarSpeedChangeEvent.h"
#include "util/events/Event.h"
#include "util/events/EventListener.h"
#include "util/events/ExceedingMaxSpeedEvent.h"
#include "util/events/NewRoadNavigationEvent.h"

namespace gui {

class NewRoadNavigationEventListener: public EventListener {
public:
	NewRoadNavigationEventListener(InfoLayer* infoLayer): EventListener(NewRoadNavigation_Event) { this->infoLayer = infoLayer; }
	~NewRoadNavigationEventListener() {}
	void execute(Event* event) {
		NewRoadNavigationEvent* roadNavigationEvent = (NewRoadNavigationEvent*)event;
		this->infoLayer->update(roadNavigationEvent->getRoadNavigation(), roadNavigationEvent->isGoingWrongWay());
	}
private:
	InfoLayer* infoLayer;
};

class CarSpeedChangeEventListener: public EventListener {
public:
	CarSpeedChangeEventListener(InfoLayer* infoLayer): EventListener(CarSpeedChange_Event) { this->infoLayer = infoLayer; }
	~CarSpeedChangeEventListener() {}
	void execute(Event* event) {
		CarSpeedChangeEvent* carSpeedChangeEvent = (CarSpeedChangeEvent*)event;
		this->infoLayer->update(carSpeedChangeEvent->getCarSpeed());
	}
private:
	InfoLayer* infoLayer;
};

class ExceedingMaxSpeedEventListener: public EventListener {
public:
	ExceedingMaxSpeedEventListener(InfoLayer* infoLayer): EventListener(ExceedingMaxSpeed_Event) { this->infoLayer = infoLayer; }
	~ExceedingMaxSpeedEventListener() {}
	void execute(Event* event) {
		ExceedingMaxSpeedEvent* exceedingMaxSpeedEvent = (ExceedingMaxSpeedEvent*)event;
		this->infoLayer->update(exceedingMaxSpeedEvent->isExceedingMaxSpeed());
	}
private:
	InfoLayer* infoLayer;
};

InfoLayer::InfoLayer(SurfaceFactory* surfaceFactory, CarController* carController, RouteController* routeController, int height): DynamicLayer(surfaceFactory), drawer(surfaceFactory) {
	carController->addEventListener(new NewRoadNavigationEventListener(this));
	carController->addEventListener(new CarSpeedChangeEventListener(this));
	carController->addEventListener(new ExceedingMaxSpeedEventListener(this));
	this->roadNavigation = routeController->getNextAction();
	this->goingWrongWay = carController->goingWrongWay();
	this->exceedingMaxSpeed = carController->isExceedingMaxSpeed();
	this->carSpeed = carController->getCarSpeed();
	this->maxCarSpeed = carController->getMaxCarSpeed();
	this->height = height;
	GUIHud guiHud(&this->drawer, this->roadNavigation, this->goingWrongWay, this->exceedingMaxSpeed, this->carSpeed, this->maxCarSpeed, this->height);
	this->updateSurface(guiHud);
}

InfoLayer::~InfoLayer() {

}

/*
 * Devuelve siempre la misma porcion ya que la capa de informacion esta siempre presente en el
 * mismo lugar.
 */
Surface* InfoLayer::getPortion(Portion portion) {
	Surface* ret = this->surfaceFactory->createSurface(portion, BLUE);
	ret->setTransparentColor(BLUE);
	Portion hudPortion = {0,0, this->completeSurface->getWidth(), this->completeSurface->getHeight()};
	ret->applySurface(this->completeSurface, hudPortion);
	return ret;
}

void InfoLayer::update(bool exceedingMaxSpeed) {
	this->exceedingMaxSpeed = exceedingMaxSpeed;
	this->genericUpdate();
}

void InfoLayer::update(RoadNavigation roadNavigation, bool goingWrongWay) {
	this->roadNavigation = roadNavigation;
	this->goingWrongWay = goingWrongWay;
	this->genericUpdate();
}

void InfoLayer::update(int carSpeed) {
	this->carSpeed = carSpeed;
	this->genericUpdate();
}

void InfoLayer::genericUpdate() {
	GUIHud guiHud(&this->drawer, this->roadNavigation, this->goingWrongWay, this->exceedingMaxSpeed, this->carSpeed, this->maxCarSpeed, this->height);
	this->updateSurface(guiHud);
}

}
